package com.itlong.cloud.property.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.app.APPServiceGetAccountDetailDTO;
import com.itlong.cloud.POJO.DTO.app.APPServiceGetAccountPageDTO;
import com.itlong.cloud.POJO.DTO.app.APPServiceTemporaryCarBillDTO;
import com.itlong.cloud.POJO.DTO.common.NettyServiceDTO;
import com.itlong.cloud.POJO.DTO.property.CalculateCostsDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyAccountGetDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.app.*;
import com.itlong.cloud.POJO.VO.property.*;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IPropertyAccountDao;
import com.itlong.cloud.property.dao.IPropertyPaymentManageDao;
import com.itlong.cloud.property.dao.IPropertyRoomInfoDao;
import com.itlong.cloud.property.service.IParkCarHttpService;
import com.itlong.cloud.property.service.IPropertyAccountService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 *     收费管理-收费规则处理接口实现.
 * </desc>
 *
 * @createDate 2018-08-09
 */
@Service
public class PropertyAccountServiceImpl implements IPropertyAccountService {
    private static final Logger LOG = LoggerFactory.getLogger(PropertyAccountServiceImpl.class); //日志对象

    @Autowired
    IPropertyAccountDao iPropertyAccountDao;

    @Autowired
    IPropertyPaymentManageDao iPropertyPaymentManageDao;

    @Autowired
    IParkCarHttpService iParkCarHttpService;

    @Autowired
    IPropertyRoomInfoDao iPropertyRoomInfoDao;

    @Autowired
    private RedisService redisService;

    @Autowired
    private MessageSender messageSender;

    /**
     * <desc>
     *     分页查询运营账单
     * <desc/>
     *
     * @param  propertyAccountGetDTO  分页查询未缴账单
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2019/06/06
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyPaymentVO> getOperateBillByPage(PropertyAccountGetDTO propertyAccountGetDTO) throws Exception {
        //分页对象
        Page<PropertyPaymentVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyAccountGetDTO, page);
        //填充返回数据集
        page.setRows(iPropertyAccountDao.getOperateBillByPage(params), iPropertyAccountDao.getOperateBillCount(params));
        return page;
    }

    /**
     * <desc>
     *      分页获取 未缴费账单
     * <desc/>
     *
     * @param propertyAccountGetDTO 分页查询未缴费账单DTO
     * @return
     * @author Qiang.S
     * @createDate 2018-08-09
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyUnpaymentVO> getUnpaymentByPage(PropertyAccountGetDTO propertyAccountGetDTO) throws Exception {
        //分页对象
        Page<PropertyUnpaymentVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyAccountGetDTO, page);
        //填充返回数据集
        page.setRows(iPropertyAccountDao.getUnpaymentByPage(params), iPropertyAccountDao.getUnpaymentCount(params));
        return page;
    }

    /**
     * <desc>
     *      分页获取 已缴费账单
     * <desc/>
     *
     * @param propertyAccountGetDTO 分页查询已缴费账单DTO
     * @return
     * @author Qiang.S
     * @createDate 2018-08-09
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyPaymentVO> getPaymentByPage(PropertyAccountGetDTO propertyAccountGetDTO) throws Exception {
        //分页对象
        Page<PropertyPaymentVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyAccountGetDTO, page);
        //填充返回数据集
        page.setRows(iPropertyAccountDao.getPaymentByPage(params), iPropertyAccountDao.getPaymentCount(params));
        return page;
    }

    /**
     * <desc>
     *     根据FeeId,或者查询条件 查询未缴账单
     * <desc/>
     *
     * @param propertyAccountGetDTO 查询条件
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2018/08/13
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<PropertyUnpaymentVO> getUnpaymentByFeeIds(PropertyAccountGetDTO propertyAccountGetDTO) throws Exception {
        String[] feeId;
        if (propertyAccountGetDTO.getFeeIds() != null && !"".equals(propertyAccountGetDTO.getFeeIds())) {
            feeId = propertyAccountGetDTO.getFeeIds().split(",");
            return iPropertyAccountDao.getUnpaymentByFeeIds(feeId,propertyAccountGetDTO.getProjectId());
        }
        //固定导出最多2000
        propertyAccountGetDTO.setCurrentPage("1");
        propertyAccountGetDTO.setPageSize("2000");
        //分页对象
        Page<PropertyPaymentVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyAccountGetDTO, page);
        return iPropertyAccountDao.getUnpaymentByPage(params);
    }

    /**
     * <desc>
     *     根据FeeId,或者查询条件 查询已缴账单
     * <desc/>
     *
     * @param propertyAccountGetDTO 查询条件
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2018/08/13
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<PropertyPaymentVO> getPaymentByFeeIds(PropertyAccountGetDTO propertyAccountGetDTO) throws Exception {
        String[] feeId;
        if (propertyAccountGetDTO.getFeeIds() != null && !"".equals(propertyAccountGetDTO.getFeeIds())) {
            feeId = propertyAccountGetDTO.getFeeIds().split(",");
            return iPropertyAccountDao.getPaymentByFeeIds(feeId,propertyAccountGetDTO.getProjectId());
        }
        //固定导出最多2000
        propertyAccountGetDTO.setCurrentPage("1");
        propertyAccountGetDTO.setPageSize("2000");
        //分页对象
        Page<PropertyPaymentVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyAccountGetDTO, page);
        return iPropertyAccountDao.getPaymentByPage(params);
    }

    /**
     * <desc>
     *     根据FeeId,或者查询条件 查询账单
     * <desc/>
     *
     * @param propertyAccountGetDTO 查询条件
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2019/06/06
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<PropertyPaymentVO> getOperatePaymentByFeeIds(PropertyAccountGetDTO propertyAccountGetDTO) throws Exception {
        String[] feeId;
        if (propertyAccountGetDTO.getFeeIds() != null && !"".equals(propertyAccountGetDTO.getFeeIds())) {
            feeId = propertyAccountGetDTO.getFeeIds().split(",");
            return iPropertyAccountDao.getOperatePaymentByFeeIds(feeId);
        }
        //固定导出最多2000
        propertyAccountGetDTO.setCurrentPage("1");
        propertyAccountGetDTO.setPageSize("2000");
        //分页对象
        Page<PropertyPaymentVO> page = new Page<>();
        //将DTO转换为Map
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyAccountGetDTO, page);
        return iPropertyAccountDao.getOperateBillByPage(params);
    }

    /**
     * <desc>
     *     查询缴费账单明细
     * <desc/>
     *
     * @param feeId 缴费账单ID
     * @param projectId 项目编号
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2018/08/15
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public PropertyAccountDetailVO getAccountDetail(String feeId, String projectId) throws Exception {
        PropertyAccountDetailVO propertyAccountDetailVO = iPropertyAccountDao.getAccounyDetail(feeId,projectId);
        if (propertyAccountDetailVO == null) {
            return null;
        }
        propertyAccountDetailVO.setPropertyAccountRecordVOS(iPropertyAccountDao.getAccountRecord(feeId,projectId));
        return propertyAccountDetailVO;
    }

    /**
     * <desc>
     *     APP获取账单详情,返回最新账单
     * <desc/>
     *
     * @param appServiceGetAccountDetailDTO APP获取账单详情条件
     * @param userId 用户编号
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2018/08/16
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public AppServiceAccountDetailVO getAccountDetailForAPP(APPServiceGetAccountDetailDTO appServiceGetAccountDetailDTO,
                                                            String userId) throws Exception {
        AppServiceAccountDetailVO appServiceAccountDetailVO;
        //获取基础账单信息
        appServiceAccountDetailVO = iPropertyAccountDao.getAccounyDetailForAPP(appServiceGetAccountDetailDTO.getFeeId(),appServiceGetAccountDetailDTO.getProjectId(),
                appServiceGetAccountDetailDTO.getRoomId(),appServiceGetAccountDetailDTO.getYear(),appServiceGetAccountDetailDTO.getMonth(),userId);
        //获取房屋列表
        List<AppServiceRoomsInfoVO> roomList = iPropertyAccountDao.getRoomList(userId,appServiceGetAccountDetailDTO.getProjectId()); //房屋列表
        if (appServiceAccountDetailVO != null) {
            //获取已有的账单时间表
            List<AppServiceAccountTimeVO> timeList = iPropertyAccountDao.getTimeList(appServiceAccountDetailVO.getRoomId()); //产生账单的时间列表
            //获取账单录入明细
            List<AppServiceRecordInfoVO> recordList = iPropertyAccountDao.getAccountRecordForAPP(appServiceAccountDetailVO.getFeeId(),appServiceGetAccountDetailDTO.getProjectId()); //账单列表
            appServiceAccountDetailVO.setRoomList(roomList);

            //如果有账单时间列表
            if (timeList != null) {
                appServiceAccountDetailVO.setTimeList(accountDateManage(timeList));
            }else{
                List<AppServiceAccountTimeVO> formatDate = new ArrayList<>();
                appServiceAccountDetailVO.setTimeList(formatDate);
            }

            //判断是阶梯收费并赋值
            for (int i=0; i<recordList.size();i++) {
                if (recordList.get(i).getMeasureType() != null && "2".equals(recordList.get(i).getMeasureType())) {
                    recordList.get(i).setLadderFeeInfo(iPropertyAccountDao.getLadderFeeInfo(recordList.get(i).getFeeRuleId()));
                }
            }
            appServiceAccountDetailVO.setRecordList(recordList);
            appServiceAccountDetailVO.setDataFlag("0");
            return appServiceAccountDetailVO;
        }
        // 无数据直接返回房屋列表
        appServiceAccountDetailVO = new AppServiceAccountDetailVO();
        appServiceAccountDetailVO.setRoomList(roomList);
        //根据是否传递roomId参数,如果传递则根据传递的参数将相对应的地址放倒最外层adress中
        if  (appServiceGetAccountDetailDTO.getRoomId() != null && !"".equals(appServiceGetAccountDetailDTO.getRoomId())) {
            for (AppServiceRoomsInfoVO rooms: roomList) {
                if (rooms.getRoomId().equals(appServiceGetAccountDetailDTO.getRoomId())) {
                    appServiceAccountDetailVO.setAddress(rooms.getAddress());
                    break;
                }
            }
        }
        appServiceAccountDetailVO.setDataFlag("1");
        return appServiceAccountDetailVO;
    }

    /**
     * <desc>
     *     查询账单缴费状态
     * <desc/>
     *
     * @param feeId 缴费账单ID
     * @param projectId 项目编号
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2018/08/15
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String getFeeStatus(String feeId, String projectId) throws Exception {
        return iPropertyAccountDao.getFeeStatus(feeId,projectId);
    }

    /**
     * <desc>
     *     账单支付
     * <desc/>
     *
     * @param feeId 缴费账单ID
     * @param projectId 项目编号
     * @param paymentType 收费方式：1现金 2银行转账 3支付宝转账 4微信转账 5小区收款码-微信 6小区收款码-支付宝 7其他支付方式
     * @param loginUserId 操作员ID
     * @return  MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2018/08/15
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<AppUserAndRoomInfoVO> payment(String feeId, String projectId, String paymentType, String loginUserId) throws Exception {
        int type = iPropertyAccountDao.getTypeByFeeId(feeId);
        if (type == 1) {
            iPropertyAccountDao.updatePaymentRecordType(feeId);
            //如所交费用为1物业费时，将发送消息队列 修改app_user_project和room_info表中用户的欠费字段和推送云对讲房间和用户的指令  由于支付OK后要极光推送故，暂不使用异步
            List<AppUserAndRoomInfoVO> list = iPropertyAccountDao.getForbiddenInfo(feeId);
            List<Map<String, Object>> roomList = new ArrayList<>();
            if (null != list && !list.isEmpty()) {
                List<String> userIdList = new ArrayList<>();
                List<String> roomIdList = new ArrayList<>();
//                JSONArray pushRoom = new JSONArray();
//                JSONObject dataJs = new JSONObject();
                for(AppUserAndRoomInfoVO roomInfoVO : list){
                    userIdList.add(roomInfoVO.getUserId());
                    roomIdList.add(roomInfoVO.getRoomId());
                    Map<String,Object> roomMap=new HashMap<>();
                    roomMap.put("roomId", roomInfoVO.getRoomId());
                    roomList.add(roomMap);
//                    JSONObject json = new JSONObject();
//                    json.put("unitId", roomInfoVO.getUnitId());
//                    json.put("buildId", roomInfoVO.getBuildId());
//                    json.put("roomId", roomInfoVO.getRoomId());
//                    pushRoom.add(json);
                }
                //修改app_user_project欠费状态
                // 通过房间id查询房间下的住户
                String roomId = iPropertyAccountDao.getFeeRoomId(feeId);
                List<String> userIdList2 = iPropertyRoomInfoDao.getUserIdsByRoomId(roomId);
                for (String userId : userIdList2) {
                    // 判断用户项目下是否还有欠费房间，没有则更新用户项目为不欠费状态
                    int arrearRoomCount = iPropertyRoomInfoDao.getArrearRoomCount(roomId, userId);
                    // 更新用户项目欠费状态
                    if (arrearRoomCount == 0) {
                        iPropertyRoomInfoDao.updateUserProjectArrearageStatus(roomId,0, userId);
                    } else {
                        iPropertyRoomInfoDao.updateUserProjectArrearageStatus(roomId,1, userId);
                    }
                }
                Integer days = iPropertyAccountDao.getMaxArrearDaysByRoomId(roomId,projectId);
                if (days == null || days <= 0) {
                    //修改room_info欠费状态
                    iPropertyAccountDao.updateRoomStatus(roomIdList);
                }

                //向云对讲推送房间信息变更指令
//                List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
//                DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
//                        new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, pushRoom.toJSONString(), list.get(0).getProjectId());
//                changeLogPOS.add(deviceBusinessChangeLogPO);
//                if (!changeLogPOS.isEmpty()) {
//                    dataJs = new JSONObject();
//                    dataJs.put("data",changeLogPOS);
//
//                    messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
//                            JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
//                            RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
//                }
            }
            iPropertyAccountDao.updatePaymentType(feeId,projectId,paymentType,loginUserId);
            if (!roomList.isEmpty()) {
                List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
                List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
                List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
                //推送房间更新消息
                DeviceBusinessChangeLogPO po = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, JsonUtil.toJSON(roomList), projectId);
                changes.add(po);
                DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(projectId, CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                elevatorChanges.add(elevatorPo);
                DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(projectId, CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                entranceChanges.add(entrancePO);
                JSONObject dataJs = new JSONObject();
                dataJs.put("data", changes);
                //发送云对讲业务指令
                messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE, JsonUtil.toJSON(dataJs),
                        RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                dataJs.put("data", elevatorChanges);
                //推送云电梯房间信息
                messageSender.send(
                        RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                        JsonUtil.toJSON(dataJs),
                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
                //发送云门禁指令
                dataJs.put("data", entranceChanges);
                messageSender.send(
                        RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                        JSON.toJSONString(dataJs),
                        RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
                );
            }
            return list;
        }
        iPropertyAccountDao.updatePaymentTypeForOther(feeId,projectId,paymentType,loginUserId);
        return null;
    }

    /**
     * <desc>
     *      APP分页获取账单列表
     * </desc>
     *
     * @param appServiceGetAccountPageDTO 获取账单列表DTO
     * @return MessageVO 标准格式化响应结果
     * @author Qiang.S
     * @createDate 2018/08/21
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<AppServiceAccountInfoALLVO> getAccountBypageForAPP(APPServiceGetAccountPageDTO appServiceGetAccountPageDTO, String userId) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(appServiceGetAccountPageDTO);
        //分页类默认pageSize为20
        Page<AppServiceAccountInfoALLVO> page = new Page<>();
        page.getPage().setPageSize(appServiceGetAccountPageDTO.getPageSize());
        page.getPage().setCurrentPage(appServiceGetAccountPageDTO.getCurrentPage());
        params.put("currentPage", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        AppServiceAccountInfoALLVO appServiceAccountInfoALLVO = new AppServiceAccountInfoALLVO();
        List<AppServiceAccountInfoVO> list = iPropertyAccountDao.getAccountBypageForAPP(params);
        //获取已有的账单时间表
        if (appServiceGetAccountPageDTO.getRoomId() != null && !"".equals(appServiceGetAccountPageDTO.getRoomId())) {
            List<AppServiceAccountTimeVO> timeList = iPropertyAccountDao.getTimeList(appServiceGetAccountPageDTO.getRoomId()); //产生账单的时间列表

            //如果有账单时间列表
            if (timeList != null) {
                appServiceAccountInfoALLVO.setTimeList(accountDateManage(timeList));
            }else{
                List<AppServiceAccountTimeVO> formatDate = new ArrayList<>();
                appServiceAccountInfoALLVO.setTimeList(formatDate);
            }
        }
        appServiceAccountInfoALLVO.setList(list);
        // 查询用户房间列表，同时应APP要求，字段另外重新更名
        List<AppServiceRoomsInfoVO> roomListOld = iPropertyAccountDao.getRoomList(userId, appServiceGetAccountPageDTO.getProjectId());
        List<AppAccountRoomInfoVO> roomList = new ArrayList<>();
        if (roomListOld != null && !roomListOld.isEmpty()) {
            for (AppServiceRoomsInfoVO roomOld : roomListOld) {
                AppAccountRoomInfoVO roomInfoVO = new AppAccountRoomInfoVO();
                roomInfoVO.setRoomId(roomOld.getRoomId());
                roomInfoVO.setRoomNum(roomOld.getAddress());
                roomList.add(roomInfoVO);
            }
        }
        appServiceAccountInfoALLVO.setRoomList(roomList);
        //填充返回数据集
        List<AppServiceAccountInfoALLVO> listAll  = new ArrayList<>();
        listAll.add(appServiceAccountInfoALLVO);
        page.setRows(listAll, iPropertyAccountDao.getAccountCountForAPP(params));
        return page;
    }

    /**
     * <desc>
     *      统计账单滞纳金
     * </desc>
     *
     * @throws Exception
     * @author wangzhi
     * @createDate 2018/08/29
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public List<PropertyArrearageBillGetVO> statisticsPenalty() throws Exception {
        Date nowTime = new Date();
        // 先获取未缴费且已逾期产生滞纳金的账单信息
        List<PropertyOverdueUnpaidBillGetVO> overdueUnpaidBillS = iPropertyAccountDao.getOverdueUnpaidBillS();
        if (overdueUnpaidBillS != null && !overdueUnpaidBillS.isEmpty()) {
            List<PropertyPaymentDataRecordPO> propertyPaymentDataRecordPOList = new ArrayList<>();
            Map<String,PropertyPaymentBillPO> map = new HashMap<>();
            // 滞纳金爆表，忽略处理账单
            Map<String, BigDecimal> feeIdPaidAmountMap = new HashMap<>();
            List<String> ignoreFeeIdList = new ArrayList<>();
            BigDecimal maxRange = new BigDecimal("999999999.99");
            for (PropertyOverdueUnpaidBillGetVO overdueUnpaidBill : overdueUnpaidBillS){
                if (ignoreFeeIdList.contains(overdueUnpaidBill.getFeeId())) {
                    continue;
                }
                // 先处理物业缴费数据录入数据
                PropertyPaymentDataRecordPO propertyPaymentDataRecordPO = new PropertyPaymentDataRecordPO();
                propertyPaymentDataRecordPO.setFeeDataId(overdueUnpaidBill.getFeeDataId());
                propertyPaymentDataRecordPO.setUpdateTime(nowTime);
                String dueAmount = overdueUnpaidBill.getDueAmount(); // 此处dueAmount已经加上了损耗，下面不用再加
                String dueDays = overdueUnpaidBill.getDueDays(); // 已滞纳天数
                String penaltyPercentage = overdueUnpaidBill.getPenaltyPercentage(); // 滞纳金百分比
                BigDecimal dueAmountValue = new BigDecimal(dueAmount == null ? "0" : dueAmount);
                // 计算滞纳金
                BigDecimal penalty =
                        dueAmountValue.multiply(new BigDecimal(penaltyPercentage)).multiply(new BigDecimal(dueDays)).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
                if (penalty == null) {
                    penalty = new BigDecimal(0);
                }
                if (penalty.compareTo(maxRange) > 0) {
                    ignoreFeeIdList.add(overdueUnpaidBill.getFeeId());
                    continue;
                }
                propertyPaymentDataRecordPO.setPenalty(penalty);
                BigDecimal lossAmount = new BigDecimal(overdueUnpaidBill.getLossAmount());
                BigDecimal paidAmount = dueAmountValue.add(penalty)/*.add(lossAmount)*/;
                // 应缴金额自然也会超出范围
                if (paidAmount.compareTo(maxRange) > 0) {
                    ignoreFeeIdList.add(overdueUnpaidBill.getFeeId());
                    continue;
                }
                // 总账单应缴金额计算并且判断
                BigDecimal feeIdPaidAmount = feeIdPaidAmountMap.get(overdueUnpaidBill.getFeeId());
                if (feeIdPaidAmount == null) {
                    feeIdPaidAmount = new BigDecimal("0");
                    feeIdPaidAmount = feeIdPaidAmount.add(paidAmount);
                    feeIdPaidAmountMap.put(overdueUnpaidBill.getFeeId(), feeIdPaidAmount);
                } else {
                    feeIdPaidAmount = feeIdPaidAmount.add(paidAmount);
                    feeIdPaidAmountMap.put(overdueUnpaidBill.getFeeId(), feeIdPaidAmount);
                    if (paidAmount.compareTo(maxRange) > 0) {
                        ignoreFeeIdList.add(overdueUnpaidBill.getFeeId());
                        continue;
                    }
                }
                propertyPaymentDataRecordPO.setPaidAmount(paidAmount);
                propertyPaymentDataRecordPOList.add(propertyPaymentDataRecordPO);
                // 处理物业缴费账单数据
                PropertyPaymentBillPO propertyPaymentBillPO = map.get(overdueUnpaidBill.getFeeId());
                if (propertyPaymentBillPO == null) {
                    propertyPaymentBillPO = new PropertyPaymentBillPO();
                    propertyPaymentBillPO.setPenalty(penalty);
                    BigDecimal partPaidAmount = penalty.add(lossAmount);
                    propertyPaymentBillPO.setPaidAmount(partPaidAmount);
                    map.put(overdueUnpaidBill.getFeeId(),propertyPaymentBillPO);
                } else {
                    BigDecimal partPaidAmount = propertyPaymentBillPO.getPaidAmount();
                    BigDecimal partPenalty = propertyPaymentBillPO.getPenalty();
                    propertyPaymentBillPO.setPenalty(partPenalty.add(penalty));
                    propertyPaymentBillPO.setPaidAmount(partPaidAmount.add(penalty).add(lossAmount));
                    map.put(overdueUnpaidBill.getFeeId(),propertyPaymentBillPO);
                }
            }
            if (!propertyPaymentDataRecordPOList.isEmpty()) {
                iPropertyAccountDao.batchUpdatePenaltyForDataRecord(propertyPaymentDataRecordPOList);
            }
            if (!map.isEmpty()) {
                iPropertyAccountDao.batchUpdatePenaltyForBill(map);
            }
        }

        // 查询出已经欠费逻辑的账单，通过欠费设备联动生效时间字段arrearage_device_date
        List<PropertyArrearageBillGetVO> propertyArrearageBillGetVOList = iPropertyAccountDao.getArrearageBills();
        if (propertyArrearageBillGetVOList != null && !propertyArrearageBillGetVOList.isEmpty()) {
            // userId和projectId连接，用于更新用户项目欠费状态
            List<String> userIdAndProjectId = new ArrayList<>();
            // roomId集合，用于更新房屋欠费状态
            Set<String> roomIdSet = new HashSet<>();
            // 用于发送消息队列设备轮询命令存储数据
            Map<String, Set<String>> roomIdMapSet = new HashMap<>();
            for(PropertyArrearageBillGetVO propertyArrearageBillGetVO : propertyArrearageBillGetVOList){
                userIdAndProjectId.add(propertyArrearageBillGetVO.getUserId() + "," + propertyArrearageBillGetVO.getProjectId());
                roomIdSet.add(propertyArrearageBillGetVO.getRoomId());
                // 放入发送消息队列设备轮询命令数据中
                if (roomIdMapSet.get(propertyArrearageBillGetVO.getProjectId()) == null) {
                    Set<String> set = new HashSet<>();
                    set.add(propertyArrearageBillGetVO.getRoomId());
                    roomIdMapSet.put(propertyArrearageBillGetVO.getProjectId(),set);
                } else {
                    Set<String> set = roomIdMapSet.get(propertyArrearageBillGetVO.getProjectId());
                    set.add(propertyArrearageBillGetVO.getRoomId());
                    roomIdMapSet.put(propertyArrearageBillGetVO.getProjectId(),set);
                }
            }
            // 更新用户项目欠费状态
            LOG.info("更新用户项目欠费状态的userId和projectId连接数据：" + userIdAndProjectId);
            iPropertyAccountDao.setUserArrearageStatus(userIdAndProjectId);
            // 更新房间欠费状态
            LOG.info("更新房屋项目欠费状态的roomId连接数据：" + roomIdSet);
            iPropertyAccountDao.setRoomArrearageStatus(roomIdSet);
            // 保存推送房间信息指令业务
            roomIdMapSet.forEach((key, value) -> {
                try {
                    List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
                    List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
                    List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
                    List<Map<String,Object>> roomList=new ArrayList<>();
                    for (String roomId : value) {
                        Map<String,Object> roomMap=new HashMap<>();
                        roomMap.put("roomId", roomId);
                        roomList.add(roomMap);
                    }
                    //推送房间更新消息
                    DeviceBusinessChangeLogPO po = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, JsonUtil.toJSON(roomList), key);
                    changes.add(po);
                    DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(key, CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                    elevatorChanges.add(elevatorPo);
                    DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(key, CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                    entranceChanges.add(entrancePO);
                    JSONObject dataJs = new JSONObject();
                    dataJs.put("data", changes);
                    //发送云对讲业务指令
                    messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE, JsonUtil.toJSON(dataJs),
                            RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                            RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                    dataJs.put("data", elevatorChanges);
                    //推送云电梯房间信息
                    messageSender.send(
                            RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                            JsonUtil.toJSON(dataJs),
                            RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                            RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
                    //发送云门禁指令
                    dataJs.put("data", entranceChanges);
                    messageSender.send(
                            RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                            JSON.toJSONString(dataJs),
                            RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                            RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
                    );
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
//            List<PropertyArrearageBillGetVO> propertyArrearageBillGetVOGroupByRoomIdList = iPropertyAccountDao.getArrearageBillGroupByRoomId();
//            List<DeviceBusinessChangeLogPO> deviceBusinessChangeLogPOList = new ArrayList<>();
//            Map<String,List<Map<String,String>>> commandParameterMap = new HashMap<>();
//            for(PropertyArrearageBillGetVO propertyArrearageBillGetVO : propertyArrearageBillGetVOGroupByRoomIdList){
//                Map<String,String> oneRoomInfo = new HashMap<>();
//                oneRoomInfo.put("buildId",propertyArrearageBillGetVO.getBuildId());
//                oneRoomInfo.put("unitId",propertyArrearageBillGetVO.getUnitId());
//                oneRoomInfo.put("roomId",propertyArrearageBillGetVO.getRoomId());
//                if (commandParameterMap.get(propertyArrearageBillGetVO.getProjectId()) == null) {
//                    List<Map<String,String>> list = new ArrayList<>();
//                    list.add(oneRoomInfo);
//                    commandParameterMap.put(propertyArrearageBillGetVO.getProjectId(),list);
//                } else {
//                    commandParameterMap.get(propertyArrearageBillGetVO.getProjectId()).add(oneRoomInfo);
//                }
//            }
//            commandParameterMap.forEach((key,value) -> {
//                DeviceBusinessChangeLogPO deviceBusinessChangeLogPO = new DeviceBusinessChangeLogPO();
//                deviceBusinessChangeLogPO.setProjectId(key);
//                deviceBusinessChangeLogPO.setStatus(0);
//                deviceBusinessChangeLogPO.setCreateTime(nowTime);
//                deviceBusinessChangeLogPO.setUpdateTime(nowTime);
//                deviceBusinessChangeLogPO.setCommandType(SmartCommunityEnum.PUSH_ROOM.getCommandType());
//                String commandParameter = JSON.toJSONString(value);
//                deviceBusinessChangeLogPO.setCommandParameter(commandParameter);
//                deviceBusinessChangeLogPO.setCommandDes(SmartCommunityEnum.PUSH_ROOM.getCommandDes());
//                deviceBusinessChangeLogPOList.add(deviceBusinessChangeLogPO);
//            });
//            iPropertyAccountDao.batchSaveDeviceBusinessChangeLog(deviceBusinessChangeLogPOList);
            // 返回数据进行极光推送至APP
            return propertyArrearageBillGetVOList;
        }
        return null;
    }

    /**
     * <desc>
     *      统计账单滞纳金
     * </desc>
     *
     * @throws Exception
     * @author wangzhi
     * @createDate 2018/08/29
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public List<PropertyArrearageBillGetVO> statisticsPenaltyForProperty(String projectId) throws Exception {
        Date nowTime = new Date();
        // 查询出已经欠费逻辑的账单，通过欠费设备联动生效时间字段arrearage_device_date
        List<PropertyArrearageBillGetVO> propertyArrearageBillGetVOList = iPropertyAccountDao.getArrearageBillGroupByProjectId(projectId);
        // 查询当前项目中处于欠费状态房间信息
        List<PropertyArrearageBillGetVO> arrearageInfo = iPropertyAccountDao.getArrearageInfoRoomIdByProjectId(projectId);
        // 保存推送房间信息指令业务
        List<PropertyArrearageBillGetVO> propertyArrearageBillGetVOGroupByRoomIdList = iPropertyAccountDao.getArrearageBillGroupByRoomIdByProjectId(projectId);
        //讲项目处于欠费状态的房间
        List<PropertyArrearageBillGetVO> newList = new ArrayList<>();
        if (propertyArrearageBillGetVOList != null && !propertyArrearageBillGetVOList.isEmpty()) {
            // userId和projectId连接，用于更新用户项目欠费状态
            List<String> userIdAndProjectId = new ArrayList<>();
            // roomId集合，用于更新房屋欠费状态
            Set<String> roomIdSet = new HashSet<>();
            for(PropertyArrearageBillGetVO propertyArrearageBillGetVO : propertyArrearageBillGetVOList){
                userIdAndProjectId.add(propertyArrearageBillGetVO.getUserId() + "," + propertyArrearageBillGetVO.getProjectId());
                roomIdSet.add(propertyArrearageBillGetVO.getRoomId());
            }
            if (arrearageInfo != null) {
                for(PropertyArrearageBillGetVO propertyArrearageBillGetVO : propertyArrearageBillGetVOGroupByRoomIdList){
                    int flag = 0;
                    for (PropertyArrearageBillGetVO arrearageRoomId:arrearageInfo) {
                        if (arrearageRoomId.getRoomId().equals(propertyArrearageBillGetVO.getRoomId())) {
                            flag =1;
                        }
                    }
                    if (flag != 1) {
                        newList.add(propertyArrearageBillGetVO);
                    }
                }
                newList.addAll(arrearageInfo);
            }

            // 更新用户项目欠费状态
            iPropertyAccountDao.updateProjectArrearageStatus(projectId);  
            iPropertyAccountDao.updateRoomArrearageStatus(projectId);
            LOG.info("更新用户项目欠费状态的userId和projectId连接数据：" + userIdAndProjectId);
            iPropertyAccountDao.setUserArrearageStatus(userIdAndProjectId);
            // 更新房间欠费状态
            LOG.info("更新房屋项目欠费状态的roomId连接数据：" + roomIdSet);
            iPropertyAccountDao.setRoomArrearageStatus(roomIdSet);
            List<DeviceBusinessChangeLogPO> deviceBusinessChangeLogPOList = new ArrayList<>();
            Map<String,List<Map<String,String>>> commandParameterMap = new HashMap<>();
            for(PropertyArrearageBillGetVO propertyArrearageBillGetVO : newList){
                Map<String,String> oneRoomInfo = new HashMap<>();
                oneRoomInfo.put("buildId",propertyArrearageBillGetVO.getBuildId());
                oneRoomInfo.put("unitId",propertyArrearageBillGetVO.getUnitId());
                oneRoomInfo.put("roomId",propertyArrearageBillGetVO.getRoomId());
                if (commandParameterMap.get(propertyArrearageBillGetVO.getProjectId()) == null) {
                    List<Map<String,String>> list = new ArrayList<>();
                    list.add(oneRoomInfo);
                    commandParameterMap.put(propertyArrearageBillGetVO.getProjectId(),list);
                } else {
                    commandParameterMap.get(propertyArrearageBillGetVO.getProjectId()).add(oneRoomInfo);
                }
            }
            commandParameterMap.forEach((key,value) -> {
                DeviceBusinessChangeLogPO deviceBusinessChangeLogPO = new DeviceBusinessChangeLogPO();
                deviceBusinessChangeLogPO.setProjectId(key);
                deviceBusinessChangeLogPO.setStatus(0);
                deviceBusinessChangeLogPO.setCreateTime(nowTime);
                deviceBusinessChangeLogPO.setUpdateTime(nowTime);
                deviceBusinessChangeLogPO.setCommandType(SmartCommunityEnum.PUSH_ROOM.getCommandType());
                String commandParameter = JSON.toJSONString(value);
                deviceBusinessChangeLogPO.setCommandParameter(commandParameter);
                deviceBusinessChangeLogPO.setCommandDes(SmartCommunityEnum.PUSH_ROOM.getCommandDes());
                deviceBusinessChangeLogPOList.add(deviceBusinessChangeLogPO);
            });
            iPropertyAccountDao.batchSaveDeviceBusinessChangeLog(deviceBusinessChangeLogPOList);
        }
        return newList;
    }

    /**
     * <desc>
     *      获取需要发送催费短信的组装信息对象
     * </desc>
     *
     * @return 催费短信组装信息对象
     * @author wangzhi
     * @createDate 2018/08/31
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<PropertyRushFeeMessageVO> getRushFeeMessage() throws Exception {
        return iPropertyAccountDao.getRushFeeMessage();
    }

    /**
     * <desc>
     *      根据房间编号获取未缴费账单个数
     * </desc>
     *
     * @param roomId 房间编号
     * @return 催费短信组装信息对象
     * @author Qiang.S
     * @createDate 2018/09/18
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Integer getAccountByRoomId(String roomId) throws Exception {
        return iPropertyAccountDao.getAccountByRoomId(roomId);
    }

    /**
     * <desc>
     *      停车业务判断
     * </desc>
     *
     * @param appServiceTemporaryCarBillDTO
     * @return 账单编号
     * @author Qiang.S
     * @createDate 2018/11/15
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public AppServiceTemporaryCarBillVO checkCarBill(APPServiceTemporaryCarBillDTO appServiceTemporaryCarBillDTO) throws Exception {
        AppServiceTemporaryCarBillVO appServiceTemporaryCarBillVO = new AppServiceTemporaryCarBillVO();
        //根据车牌在入出场记录中查询未出场车辆相关信息
        PropertyParkPassRecordVO propertyParkPassRecordVO = iPropertyAccountDao.getParkingInfo(appServiceTemporaryCarBillDTO.getPlateNumber());
        if (propertyParkPassRecordVO == null) {
            appServiceTemporaryCarBillVO.setIsParkingFlag("0");
            return appServiceTemporaryCarBillVO;
        }
        //判断车辆是否是月卡用户
        if (iPropertyAccountDao.getCarMonthCardInfoByPlateNumber(propertyParkPassRecordVO.getProjectId(),appServiceTemporaryCarBillDTO.getPlateNumber()) > 0) {
            //如果是进场之后办理的月卡则按临时车处理
            if (iPropertyAccountDao.getCarMonthCardInfoByInTime(propertyParkPassRecordVO.getProjectId(),
                    appServiceTemporaryCarBillDTO.getPlateNumber(),propertyParkPassRecordVO.getInTime()) == 0) {
                appServiceTemporaryCarBillVO.setMoonCarFlag("0");
            }
        }
        appServiceTemporaryCarBillVO.setProjectId(propertyParkPassRecordVO.getProjectId());
        appServiceTemporaryCarBillVO.setStatus(propertyParkPassRecordVO.getStatus());
        return appServiceTemporaryCarBillVO;
    }

    /**
     * <desc>
     *      生成临时车辆停车账单
     * </desc>
     *
     * @param appServiceTemporaryCarBillDTO 生成账单必要信息
     * @param userId 用户编号
     * @return
     * @author Qiang.S
     * @createDate 2018/11/07
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public AppServiceTemporaryCarBillVO temporaryCarBill(APPServiceTemporaryCarBillDTO appServiceTemporaryCarBillDTO, String userId) throws Exception {
        AppServiceTemporaryCarBillVO appServiceTemporaryCarBillVO = new AppServiceTemporaryCarBillVO();
        //根据车牌在入出场记录中查询未出场车辆相关信息
        PropertyParkPassRecordVO propertyParkPassRecordVO = iPropertyAccountDao.getParkingInfo(appServiceTemporaryCarBillDTO.getPlateNumber());
        if (propertyParkPassRecordVO == null) {
            appServiceTemporaryCarBillVO.setIsParkingFlag("0");
            return appServiceTemporaryCarBillVO;
        }
        //判断车辆是否是月卡用户
        if (iPropertyAccountDao.getCarMonthCardInfoByPlateNumber(propertyParkPassRecordVO.getProjectId(),appServiceTemporaryCarBillDTO.getPlateNumber()) > 0) {
            //如果是进场之后办理的月卡则按临时车处理
            if (iPropertyAccountDao.getCarMonthCardInfoByInTime(propertyParkPassRecordVO.getProjectId(),
                    appServiceTemporaryCarBillDTO.getPlateNumber(),propertyParkPassRecordVO.getInTime()) == 0) {
                appServiceTemporaryCarBillVO.setMoonCarFlag("0");
                return appServiceTemporaryCarBillVO;
            }
        }
        if ("".equals(userId)) {
            userId = iPropertyAccountDao.getUserIdByCarNum(appServiceTemporaryCarBillDTO.getPlateNumber(),propertyParkPassRecordVO.getProjectId());
        }
        //如果有优惠券则减免优惠券金额
        PropertyParkCouponGetOneVO propertyParkCouponGetOneVO = null;
        if (appServiceTemporaryCarBillDTO.getRedeemCode() != null && !"".equals(appServiceTemporaryCarBillDTO.getRedeemCode())) {//传入优惠卷
            propertyParkCouponGetOneVO = iPropertyAccountDao.getOneCoupon(appServiceTemporaryCarBillDTO.getRedeemCode(),null, "1");
        }
        //根据入场标识计算临时停车费用
        BigDecimal paidAmount = new BigDecimal("0.00");//实缴
        if (propertyParkCouponGetOneVO == null) {//不使用优惠券
            propertyParkCouponGetOneVO = new PropertyParkCouponGetOneVO();
            propertyParkCouponGetOneVO.setType(2);
            propertyParkCouponGetOneVO.setDerate("");
            if (appServiceTemporaryCarBillDTO.getIsCoupon() != null && "0".equals(appServiceTemporaryCarBillDTO.getIsCoupon())) {
                propertyParkCouponGetOneVO.setParkCouponId("");
            }
        }
        BigDecimal dueAmount = appServiceTemporaryCarBillDTO.getAccountOld();//不适用优惠券计算的停车费用
        //如果优惠卷是免金额
        if (propertyParkCouponGetOneVO.getType() == 2 && (appServiceTemporaryCarBillDTO.getRedeemCode() != null && !"".equals(appServiceTemporaryCarBillDTO.getRedeemCode()))) {
            LOG.info("dueAmount:"+dueAmount+" derate:"+propertyParkCouponGetOneVO.getDerate());
            paidAmount = dueAmount.subtract(new BigDecimal(propertyParkCouponGetOneVO.getDerate()));
            if (paidAmount.signum() == -1) {
                paidAmount = new BigDecimal("0");
            }
        } else {
            paidAmount = appServiceTemporaryCarBillDTO.getAccount();
        }
        LOG.info("paidAmount:"+paidAmount);
        Date nowTime = new Date();
        PropertyPaymentBillPO propertyPaymentBillPO = new PropertyPaymentBillPO();
        propertyPaymentBillPO.setUserId(userId);
        //查询是否已经生成了此账单,如果已有则只更新金额
        if (propertyParkPassRecordVO.getFeeId() != null && !"".equals(propertyParkPassRecordVO.getFeeId())) {
            propertyPaymentBillPO.setFeeId(propertyParkPassRecordVO.getFeeId());
            propertyPaymentBillPO.setPenalty(new BigDecimal("0.00"));
            propertyPaymentBillPO.setUpdateTime(nowTime);

            //当前账单状态为未支付
            if ("1".equals(propertyParkPassRecordVO.getFeeStatus())) {
                propertyPaymentBillPO.setDueAmount(dueAmount);
                propertyPaymentBillPO.setPaidAmount(paidAmount);
            }
            //当前账单状态为已支付
            if ("2".equals(propertyParkPassRecordVO.getFeeStatus()) && dueAmount.compareTo(new BigDecimal("0.00")) != 0 && propertyParkCouponGetOneVO != null) {
                if ((dueAmount.compareTo(new BigDecimal("0.00")) == 0 && propertyParkCouponGetOneVO != null) || dueAmount.compareTo(new BigDecimal("0.00")) != 0) {
                    propertyPaymentBillPO.setDueAmount(dueAmount);
                    propertyPaymentBillPO.setPaidAmount(paidAmount);
                    propertyPaymentBillPO.setFeeStatus(1);
                }
            }

            iPropertyPaymentManageDao.update(SqlUtil.durableData(propertyPaymentBillPO,PlatformConstants.TABLE_UPDATE));
            //判断是否可以继续使用优惠卷
            if (iPropertyAccountDao.checkIsCoupon(propertyParkPassRecordVO.getFeeId()) > 0) {
                appServiceTemporaryCarBillVO.setIsCoupon("1");//不可以使用优惠卷
                propertyParkCouponGetOneVO.setParkCouponId(null);
            }
        }else {
            //生成临时停车账单并返回
            propertyPaymentBillPO.setFeeId(LogicIdUtil.bussinessId());
            propertyPaymentBillPO.setFeeNumber(this.getFeeNumber(propertyParkPassRecordVO.getProjectId()));
            //根据车牌,项目编号获取用户详细信息
            PropertyCarGetOneVO propertyCarGetOneVO = iPropertyAccountDao.getOneBasicCar(userId,appServiceTemporaryCarBillDTO.getPlateNumber());
            if (propertyCarGetOneVO != null) {
                propertyPaymentBillPO.setBuildId(propertyCarGetOneVO.getBuildId());
                propertyPaymentBillPO.setUnitId(propertyCarGetOneVO.getUnitId());
                propertyPaymentBillPO.setRoomId(propertyCarGetOneVO.getRoomId());
                Map<String,Object> userInfo = iPropertyPaymentManageDao.getUserPhoneByRoomId(propertyCarGetOneVO.getRoomId());
                propertyPaymentBillPO.setRealName(StringHandlerUtil.getNullOrStringForObject(userInfo.get("realName")));
                propertyPaymentBillPO.setPhoneNum(StringHandlerUtil.getNullOrStringForObject(userInfo.get("phoneNum")));
            }

            propertyPaymentBillPO.setDueAmount(dueAmount);
            propertyPaymentBillPO.setPaidAmount(paidAmount);
            propertyPaymentBillPO.setPenalty(new BigDecimal("0.00"));

            Calendar cal1 = Calendar.getInstance();
            cal1.setTime(nowTime);
            cal1.set(Calendar.DAY_OF_MONTH,1);
            cal1.add(Calendar.MONTH, 0);
            propertyPaymentBillPO.setStartTime(cal1.getTime());
            Calendar cal2 = Calendar.getInstance();
            cal2.set(Calendar.DAY_OF_MONTH, cal2.getActualMaximum(Calendar.DAY_OF_MONTH));
            propertyPaymentBillPO.setEndTime(cal2.getTime());
            propertyPaymentBillPO.setType(3);
            propertyPaymentBillPO.setProjectId(propertyParkPassRecordVO.getProjectId());
            propertyPaymentBillPO.setFeeStatus(1);
            propertyPaymentBillPO.setStatus(DataStatusEnum.NORMAL.getType());
            propertyPaymentBillPO.setCreateTime(nowTime);
            iPropertyPaymentManageDao.save(SqlUtil.durableData(propertyPaymentBillPO, PlatformConstants.TABLE_SAVE));
        }
        iPropertyAccountDao.updateParkRecord(propertyParkPassRecordVO.getParkingId(),propertyPaymentBillPO.getFeeId(),propertyParkCouponGetOneVO.getParkCouponId());
        //LOG.info("更新通行记录表,优惠券号:"+propertyParkCouponGetOneVO.getParkCouponId()+" 账单编号:"+propertyPaymentBillPO.getFeeId());

        appServiceTemporaryCarBillVO.setProjectName(propertyParkPassRecordVO.getProjectName());
        appServiceTemporaryCarBillVO.setProjectId(propertyParkPassRecordVO.getProjectId());
        appServiceTemporaryCarBillVO.setFeeId(propertyPaymentBillPO.getFeeId());
        appServiceTemporaryCarBillVO.setParkName(propertyParkPassRecordVO.getProjectName() + "停车场");
        String endTime = DateUtil.fomatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
        appServiceTemporaryCarBillVO.setParkTimeSlot(propertyParkPassRecordVO.getInTime()+" 至 " + endTime);
        //看自己的时间格式选择对应的转换对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTime = propertyParkPassRecordVO.getInTime();
        //转换成date类型
        Date start = sdf.parse(startTime);
        Date end = sdf.parse(endTime);
        //获取毫秒数
        Long startLong = start.getTime();
        Long endLong = end.getTime();
        //计算时间差,单位毫秒
        Long ms = endLong-startLong;
        appServiceTemporaryCarBillVO.setParkingTime(this.longTimeToDay(ms));
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        appServiceTemporaryCarBillVO.setDueAmount(decimalFormat.format(dueAmount));
        appServiceTemporaryCarBillVO.setPaidAmount(decimalFormat.format(paidAmount));

        return appServiceTemporaryCarBillVO;
    }

    /**
     * <desc>
     *      临时停车账单到账业务
     * </desc>
     *
     * @param feeId 账单编号
     * @param account 支付金额
     * @param transactionId 支付订单第三方编号
     * @param tradeId 支付订单编号
     * @param realTotal 去手续费金额
     * @return
     * @author Qiang.S
     * @createDate 2018/11/08
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void parkingBillPay(String feeId, String account,String projectId,String transactionId,String tradeId,String realTotal) throws Exception {
        //根据账单号查询是否使用优惠券
        PropertyParkPassRecordVO propertyParkPassRecordVO = iPropertyAccountDao.getParkingInfoByFeeId(feeId);
        //如果有优惠券则减免优惠券金额
        PropertyParkCouponGetOneVO propertyParkCouponGetOneVO = null;
        if (propertyParkPassRecordVO.getParkCouponId() != null && !"".equals(propertyParkPassRecordVO.getParkCouponId())) {
            propertyParkCouponGetOneVO = iPropertyAccountDao.getOneCoupon(null,propertyParkPassRecordVO.getParkCouponId(),null);
        }
        //进行到账处理
        iPropertyAccountDao.updatePaymentTypeForParking(feeId,"2","2", PaymentTypeEnum.WECHAT_PAY.getType().toString());

        if (propertyParkCouponGetOneVO != null && propertyParkCouponGetOneVO.getParkCouponId() != null && !"".equals(propertyParkCouponGetOneVO.getParkCouponId())) {
            iPropertyAccountDao.updateCouponUseStatus(propertyParkPassRecordVO.getParkCouponId());//更新优惠卷状态
            //LOG.info("更新优惠券状态,账单编号:"+feeId+" 车牌:"+propertyParkPassRecordVO.getPlateNumber());
        }
        if (account != null && !"0".equals(account)) {
            //更新支付订单表
            PaymentTradePO orderPO = new PaymentTradePO();
            orderPO.setTradeId(tradeId);
            orderPO.setSuccessTime(new Date());
            orderPO.setUpdateTime(new Date());
            orderPO.setTradeStatus(PayStatusEnum.SUCCESS_PAY.getType());
            orderPO.setTransactionId(transactionId);
            orderPO.setSuccessReturn(PaySuccessReturnEnum.IS_RETURN.getType());
            iPropertyPaymentManageDao.update(SqlUtil.durableData(orderPO, PlatformConstants.TABLE_UPDATE));

            // 判断是否开启物业增值，如果开启，则按原来的走，未开启，则走新的授权支付流程，0是未开启，原来的支付流程钱直接流向物业，不做实时余额的变动和资金变动明细的保存
            ProjectPO projectInfo = iPropertyAccountDao.getProjectInfo(projectId);
            if (projectInfo.getPropertyValueOpen() == 1) {
                //账单到账处理完成后进行项目资金以及资金变动明细业务调整
                //保存微信支付成功后的项目中物业可提现余额和实时余额需更新 发送消息队列
                Map<String,Object> params=new HashMap<>();
                params.put("arithmeticFlag", "0");//运算: 0加,1减
                params.put("amount", realTotal);//金额
                params.put("projectId", projectId);//项目编号
                params.put("updateNameFlag",1);//0可提现余额,1实时余额   为空都更新

                messageSender.send(RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_MANAGER_QUEUE, JSON.toJSONString(params),
                        RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_ROUTING_KEY);

                //保存微信支付成功后资金变动明细 发送消息队列
                AmountChangeInfoPO changeInfoPO = new AmountChangeInfoPO(LogicIdUtil.bussinessId(),
                        new BigDecimal(account),transactionId,
                        "","");
                changeInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
                changeInfoPO.setProjectId(projectId);
                changeInfoPO.setCreateTime(new Date());
                changeInfoPO.setThirdPartyPayment(1);
                changeInfoPO.setHandlingFee(new BigDecimal("0"));
                changeInfoPO.setTradeType(TradeTypeEnum.PARKING_FEE.getType());
                JSONObject js = new JSONObject();
                js.put("data",changeInfoPO);
                messageSender.send(RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_MANAGER_QUEUE,JSON.toJSONString(js),
                        RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                        RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_ROUTING_KEY);
            }
        }
    }

    /**
     * <desc>
     *      生成账单流水
     *      处理账单时间方法
     *      生成账单流水
     * </desc>
     *
     * @param projectId 项目编号
     * @return 账单编号
     * @author Qiang.S
     * @createDate 2018/11/07
     */
    private String getFeeNumber(String projectId) throws ParseException {
        //生成费用单号 规则年月日+六位流水号，如180720000001
        String date = DateUtil.fomatDate(new Date(), "yyMMdd");
        //从缓存中获取流水号
        String redisKey = RedisConstant.REDIS_PAYMENT_BILL_SERIAL_NUMBER_CACHE+projectId+date;
        Integer tradeNo = (Integer)redisService.getObject(redisKey, Integer.class);
        if(tradeNo == null){
            //查询数据库中是否有当前流水号，有的话将当前流水号放入缓存中且+1赋值给tradeNo
            String feeNumber = iPropertyPaymentManageDao.getFeeNumberByDate(DateUtil.fomatDate(new Date(), "yyyy-MM-dd"),projectId);
            if(StringUtils.isBlank(feeNumber)){
                tradeNo = 1;
            }else{
                tradeNo = Integer.valueOf(feeNumber);
                tradeNo += 1;
            }
        }else{
            tradeNo+=1;
        }
        redisService.set(redisKey,RedisConstant.REDIS_PAYMENT_BILL_SERIAL_NUMBER_CACHE_TIME,tradeNo);
        return date+StringHandlerUtil.autlSupply(6,tradeNo.toString(),"0");
    }

    /**
     * <desc>
     *      处理账单时间方法
     * </desc>
     *
     * @param timeList 数据库查询时间结果
     * @return 账单时间整合处理结果
     * @author Qiang.S
     * @createDate 2018/09/12
     */
    private List<AppServiceAccountTimeVO> accountDateManage(List<AppServiceAccountTimeVO> timeList) throws ParseException {
        List<AppServiceAccountTimeVO> formatDate = new ArrayList<>();
        Calendar cld = Calendar.getInstance();
        AppServiceAccountTimeVO appServieAccountTimeVO = new AppServiceAccountTimeVO();
        String year = null;
        String month;
        for (int y=0;y<timeList.size();y++) {
            String date = timeList.get(y).getStartTime();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月
            Date now =sdf.parse(date);
            cld.setTime(now);
            month = cld.get(Calendar.MONTH)+1 +"";
            if (month.length() == 1) {
                month = "0"+month;
            }
            //当前年不等于上一个月份的年 重新初始化
            if (year != null && !year.equals(cld.get(Calendar.YEAR)+"")) {
                formatDate.add(appServieAccountTimeVO);
                appServieAccountTimeVO = new AppServiceAccountTimeVO();
            }
            appServieAccountTimeVO.setYear(cld.get(Calendar.YEAR)+"");
            if (appServieAccountTimeVO.getMonth() != null) {
                appServieAccountTimeVO.setMonth(appServieAccountTimeVO.getMonth()+","+month);
            }else {
                appServieAccountTimeVO.setMonth(month);
            }
            year = cld.get(Calendar.YEAR)+"";
        }
        //插入最后一条
        if (appServieAccountTimeVO.getYear() != null && appServieAccountTimeVO.getMonth() != null) {
            formatDate.add(appServieAccountTimeVO);
        }
        return formatDate;
    }

    /**
     * <desc>
     *      计算停车费金额
     * </desc>
     *
     * @param plateNumber 车牌
     * @param redeemCode 兑换码
     * @param projectId 项目编号
     * @return 账单编号
     * @author Qiang.S
     * @createDate 2018/11/12
     */
    @Override
    public NettyServiceDTO calculationAmount(String plateNumber, String redeemCode, String projectId) throws Exception {
        PropertyParkPassRecordVO propertyParkPassRecordVO = iPropertyAccountDao.getParkingInfo(plateNumber);
        PropertyParkCouponGetOneVO propertyParkCouponGetOneVO = null;
        if (redeemCode != null && !"".equals(redeemCode)) {//传入优惠卷
            propertyParkCouponGetOneVO = iPropertyAccountDao.getOneCoupon(redeemCode,null, "1");
        }
        //根据入场标识计算临时停车费用
        BigDecimal paidAmount = new BigDecimal("0.00");//实缴
        if (propertyParkCouponGetOneVO == null) {//不使用优惠券
            propertyParkCouponGetOneVO = new PropertyParkCouponGetOneVO();
            propertyParkCouponGetOneVO.setType(2);
            propertyParkCouponGetOneVO.setDerate("");
        }
        CalculateCostsDTO ccDTO = new CalculateCostsDTO();
        Date day=new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //如果优惠类型是分钟则用开始时间+优惠时间
        if (propertyParkCouponGetOneVO.getType() == 1) {
            Date dt=df.parse(propertyParkPassRecordVO.getInTime());
            Calendar rightNow = Calendar.getInstance();
            rightNow.setTime(dt);
            DecimalFormat decimalFormat = new DecimalFormat("0");
            decimalFormat.setRoundingMode(RoundingMode.HALF_UP);

            rightNow.add(Calendar.MINUTE,Integer.parseInt(decimalFormat.format(new BigDecimal(propertyParkCouponGetOneVO.getDerate()).multiply(new BigDecimal("60")))));
            if (dt.getTime() > day.getTime()) {
                ccDTO.setBeginTime(df.format(day));
            }else {
                ccDTO.setBeginTime(df.format(rightNow.getTime()));
            }
        }
        ccDTO.setEndTime(df.format(day));
        ccDTO.setGid(propertyParkPassRecordVO.getGid());
        ccDTO.setID(propertyParkPassRecordVO.getId());
        ccDTO.setParkId(propertyParkPassRecordVO.getParkId());
        ccDTO.setParkingId(propertyParkPassRecordVO.getParkingId());
        ccDTO.setRid(propertyParkPassRecordVO.getRid());
        ccDTO.setTcmId(propertyParkPassRecordVO.getTcmId());
        ccDTO.setTokenId(propertyParkPassRecordVO.getTokenId());
        ccDTO.setType(propertyParkCouponGetOneVO.getType());
        ccDTO.setIsLegal(true);
        ccDTO.setProjectId(projectId);
        //LOG.info("project:"+projectId);
        return iParkCarHttpService.queryParkCarFee(ccDTO);
    }

    /**
     * <desc>
     *      查询全部欠费账单
     * </desc>
     *
     * @param projectId 项目编号
     * @param deviceId 设备序号
     * @param deviceType 设备类型 1云电梯 2云门禁 3云对讲
     * @param roomId 房间编号
     * @param userId 用户编号
     * @return 账单编号
     * @author Qiang.S
     * @createDate 2019/05/28
     */
    @Override
    public H5ServiceAccountInfoVO getAllArrearsBill(String projectId, String deviceId, String deviceType, String roomId, String userId) throws Exception {
        //处理设备编号
        String deviceUnique = String.format("%s%s%s", projectId, deviceType, deviceId);
        //判断锁定楼栋还是单元
        Integer flag = 0;//0单元,1楼栋
        if ("2".equals(deviceType)) {
            flag = iPropertyAccountDao.getEntranceType(deviceUnique);
        }else if ("3".equals(deviceType)) {
            flag = iPropertyAccountDao.getIntercomType(deviceUnique);
        }
        if (flag == null) {
            return null;
        }
        //根据设备类型获取账单精确到栋还是单元
        //房间编号为空时使用设备地址查询查询用户相关地址下所有欠费账单
        //用户编号为空时根据房间查询出业主,之后查询出房间地址下所有欠费账单
        H5ServiceAccountInfoVO h5;
        if (roomId != null && !"".equals(roomId)) {
            String[] roomIds = roomId.split(",");
            h5 = iPropertyAccountDao.getAllArrearsBill(projectId,deviceUnique,deviceType,flag,roomIds,userId);
        }else {
            h5 = iPropertyAccountDao.getAllArrearsBill(projectId,deviceUnique,deviceType,flag,null,userId);
        }
        PropertyValuePO po = iPropertyAccountDao.getPropertyValueInfo(projectId);
        if (h5 == null) {
            h5 = new H5ServiceAccountInfoVO();
        }
        h5.setDeploy(po != null?po.getOpenTempPass().toString():"0");
        h5.setUserId((userId == null || "".equals(userId))?iPropertyAccountDao.getUserIdByRoomId(roomId.split(",")[0]):userId);
        h5.setRoomList(iPropertyAccountDao.getRoomList(h5.getUserId(),projectId)); //房屋列表);
        h5.setDeviceUnique(deviceUnique);
        return h5;
    }

    /**
     * <desc>
     *      查询小程序全部欠费账单
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId 用户编号
     * @return
     * @author Qiang.S
     * @createDate 2019/06/03
     */
    @Override
    public H5ServiceAccountInfoVO getAllArrearsBillForMini(String projectId, String userId) throws Exception {
        H5ServiceAccountInfoVO h5 = iPropertyAccountDao.getAllArrearsBillForMini(projectId,userId);
        if (h5 == null) {
            h5 = new H5ServiceAccountInfoVO();
        }
        h5.setRoomList(iPropertyAccountDao.getRoomList(userId,projectId)); //房屋列表);
        return h5;
    }

    /**
     * <desc>
     *      创建并获取临时通行账单
     * </desc>
     *
     * @param projectId 项目编号
     * @param userId 用户编号
     * @return
     * @author Qiang.S
     * @createDate 2019/05/28
     */
    @Override
    public H5ServiceTemporaryPassageBillVO createTemporaryPassageBill(String projectId,String userId) throws Exception {
        //根据项目编号查询物业增值信息
        PropertyValuePO propertyValuePO = iPropertyAccountDao.getPropertyValueInfo(projectId);
        if (propertyValuePO == null) {
            return null;
        }
        Date nowTime = new Date();
        PropertyPaymentBillPO propertyPaymentBillPO = new PropertyPaymentBillPO();
        propertyPaymentBillPO.setFeeId(LogicIdUtil.bussinessId());
        propertyPaymentBillPO.setFeeNumber(this.getFeeNumber(projectId));
        AppUserInfoPO appUserInfoPO = iPropertyAccountDao.getBaseUserInfo(userId);
        propertyPaymentBillPO.setUserId(userId);
        propertyPaymentBillPO.setRealName(appUserInfoPO.getRealName());
        propertyPaymentBillPO.setPhoneNum(appUserInfoPO.getPhoneNum());
        propertyPaymentBillPO.setTemporaryFlag(0);

        propertyPaymentBillPO.setDueAmount(propertyValuePO.getTempPassMoney());
        propertyPaymentBillPO.setPaidAmount(propertyValuePO.getTempPassMoney());
        propertyPaymentBillPO.setPenalty(new BigDecimal("0.00"));
        propertyPaymentBillPO.setStartTime(nowTime);
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(nowTime);
        cal1.add(Calendar.MINUTE, propertyValuePO.getTempPassOpenTime());
        propertyPaymentBillPO.setEndTime(cal1.getTime());
        propertyPaymentBillPO.setType(5);
        propertyPaymentBillPO.setProjectId(projectId);
        propertyPaymentBillPO.setFeeStatus(1);
        propertyPaymentBillPO.setStatus(DataStatusEnum.NORMAL.getType());
        propertyPaymentBillPO.setCreateTime(nowTime);
        iPropertyPaymentManageDao.save(SqlUtil.durableData(propertyPaymentBillPO, PlatformConstants.TABLE_SAVE));
        H5ServiceTemporaryPassageBillVO h5ServiceTemporaryPassageBillVO = new H5ServiceTemporaryPassageBillVO();
        h5ServiceTemporaryPassageBillVO.setFeeId(propertyPaymentBillPO.getFeeId());
        h5ServiceTemporaryPassageBillVO.setTempPassMoney(propertyValuePO.getTempPassMoney().toString());
        h5ServiceTemporaryPassageBillVO.setTempPassOpenTime(propertyValuePO.getTempPassOpenTime().toString());
        return h5ServiceTemporaryPassageBillVO;
    }

    /**
     * <desc>
     *      查询用户历史账单
     * </desc>
     *
     * @param projectId 项目编号
     * @param roomId 房间编号
     * @return
     * @author Qiang.S
     * @createDate 2019/06/03
     */
    @Override
    public List<H5ServiceAccountListVO> getUserBillListH5(String projectId,String roomId) throws Exception {
        List<H5ServiceAccountListVO> h5vo = iPropertyAccountDao.getUserBillDateList(projectId,roomId);
        if (h5vo != null) {
            for (H5ServiceAccountListVO year : h5vo) {
                year.setH5ServiceAccountInfoVOS(iPropertyAccountDao.getUserBillListByYear(projectId,roomId,year.getYear()));
            }
        }
        return h5vo;
    }

    /**
     * <desc>
     *      获取待推送缴费通知的账单信息
     * </desc>
     *
     * @return 待推送缴费通知的账单信息
     * @author wangzhi
     * @createDate 2019/06/13
     */
    @Override
    public List<PropertyPaymentBillPO> getPushPayNoticeBill() throws Exception {
        List<PropertyPaymentBillPO> propertyPaymentBillPOList = iPropertyAccountDao.getRushPayNoticeBill();
        // 1.8.5版本先注掉，1.8.6合并代码后打开注释
        List<PropertyPaymentBillPO> messageUserList = iPropertyAccountDao.getMessageUserList();
        propertyPaymentBillPOList.addAll(messageUserList);
        return propertyPaymentBillPOList;
    }

    /**
     * <desc>
     *      处理时间差格式化方法
     * </desc>
     *
     * @param ms 时间差
     * @return 时间格式化结果
     * @author Qiang.S
     * @createDate 2018/11/16
     */
    private String longTimeToDay(Long ms){
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;

        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;

        StringBuffer sb = new StringBuffer();
        if(day > 0) {
            sb.append(day+"天");
        }
        if(hour > 0) {
            sb.append(hour+"小时");
        }
        if(minute > 0) {
            sb.append(minute+"分");
        }
        if(second > 0) {
            sb.append(second+"秒");
        }
        if(milliSecond > 0) {
            sb.append(milliSecond+"毫秒");
        }
        return sb.toString();
    }
}
